/*
 * @Author: “ygnnli” “1585923072@qq.com”
 * @Date: 2024-08-04 15:46:19
 * @LastEditors: “ygnnli” “1585923072@qq.com”
 * @LastEditTime: 2024-08-04 16:57:24
 * @FilePath: /110/51/command_server/CommandExcute.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <set>
#include "Log.hpp"

const std::string sep = " ";
class Command
{
private:
    void LoadConf(const std::string &conf)
    {
        std::ifstream in(conf); // 打开文件路径
        if (!in.is_open())
        {
            LOG(FATAL, "open %s error\n", conf.c_str()); // 打开失败，记录日志
            return;
        }
        std::string line;
        while (std::getline(in, line)) // 逐行读取文件
        {
            LOG(DEBUG, "load command [%s] sucess\n", line.c_str()); //
            _safe_cmd.insert(line);                                 // 将读取到的内容插入到set中
        }
        in.close();
    }

public:
    Command(const std::string &cond_path) : _cond_path(cond_path)
    {
        LoadConf(_cond_path);
    }

    ~Command()
    {
    }

    std::string PrefixCommand(const std::string &cmd)
    {
        if (cmd.empty())
            return std::string(); // 空字符串返回空字符串
        auto pos = cmd.find(sep);
        if (pos == std::string::npos)
            return cmd; // 没有找到返回整个字符串
        else
            return cmd.substr(0, pos); // 找到返回这个命令前缀
    }

    bool SafeCheck(const std::string &cmd)
    {

        std::string prefix = PrefixCommand(cmd); // 获取命令的前缀
        auto iter = _safe_cmd.find(cmd);         // 查找set中是否存在该命令
        if (iter == _safe_cmd.end())             // 不存在
            return false;

        return true;
    }

    std::string Excute(const std::string &cmd) // 命令 ls -a -l
    {
        // 1. fork && pipe
        // 2. exec
        // 2.1 dup
        std::string result;
        if (SafeCheck(cmd))
        {
            FILE *fp = popen(cmd.c_str(), "r"); // "r" 读取 popen相当于把上面都做了，返回一个文件指针
            if (fp == nullptr)
            {
                return "failed";
            }

            char buffer[1024];
            while (fgets(buffer, sizeof(buffer), fp) != NULL) // 读取文件指针中的内容按行
            {
                result += buffer;
            }
            pclose(fp);
        }
        else
        {
            result = "不恰当的命令\n";
        }

        return result;
    }

private:
    std::set<std::string> _safe_cmd; // 存储安全的命令
    std::string _cond_path;          // 存储命令的路径
};